﻿using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Extensions.Logging;
using Serilog.Filters;
using Serilog.Settings.Configuration;

namespace Huioo.Learning.Serilog.ConsoleApp2
{
    internal class Program
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
                .Build();

            var logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration)
                .CreateLogger();

            logger.Information("Hello, world!");

            logger.Information("About to process input: {@MyDto} ...", new MyDto(100000, "ABC"));

            logger.Verbose(    "Verbose     - Ah, there you are!");
            logger.Debug(      "Debug       - Ah, there you are!");
            logger.Information("Information - Ah, there you are!");
            logger.Warning(    "Warning     - Ah, there you are!");
            logger.Error(      "Error       - Ah, there you are!");
            logger.Fatal(      "Fatal       - ErrorAh, there you are!");

        }

        static Logger CreateLogger1(IConfiguration hostConfig)
        {
            //自动发现与 Serilog 相关的程序集，指定源程序集作为依赖上下文
            //在非标准依赖项管理的情况下，您可以传递自定义 DependencyContext 对象：
            var functionDependencyContext = DependencyContext.Load(typeof(Startup).Assembly);

            var options = new ConfigurationReaderOptions(functionDependencyContext)
            {
                SectionName = "AzureFunctionsJobHost:Serilog" /* 使用自定义配置节，新名称 */
            };
            var logger = new LoggerConfiguration()
                .ReadFrom.Configuration(hostConfig, options)
                .CreateLogger();
            return logger;
        }

        static Logger CreateLogger2(IConfiguration configuration)
        {
            //手动传递指定的配置程序集
            var configurationAssemblies = new[]
            {
                typeof(ConsoleLoggerConfigurationExtensions).Assembly,
                typeof(FileLoggerConfigurationExtensions).Assembly,
            };
            var options = new ConfigurationReaderOptions(configurationAssemblies);
            var logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration, options)
                .CreateLogger();
            return logger;
        }

        static Logger CreateLogger3(IConfiguration configuration)
        {
            //使用 LoggingLevelSwitch，动态更新记录器的级别
            var allSwitches = new Dictionary<string, LoggingLevelSwitch>();
            var options = new ConfigurationReaderOptions
            {
                OnLevelSwitchCreated = (switchName, levelSwitch) => 
                    allSwitches[switchName] = levelSwitch
            };

            var logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration, options)
                .CreateLogger();

            LoggingLevelSwitch controlSwitch = allSwitches["$controlSwitch"];
            return logger;
        }

        static Logger CreateLogger4(IConfiguration configuration)
        {
            //使用 ILoggingFilterSwitch，动态更新接收器的过滤器
            var filterSwitches = new Dictionary<string, ILoggingFilterSwitch>();
            var options = new ConfigurationReaderOptions
            {
                OnFilterSwitchCreated = (switchName, filterSwitch) => 
                    filterSwitches[switchName] = filterSwitch
            };

            var logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration, options)
                .CreateLogger();

            ILoggingFilterSwitch filterSwitch = filterSwitches["filterSwitch"];
            return logger;
        }

    }

    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<ILoggerProvider>(sp =>
            {
                var functionDependencyContext = DependencyContext.Load(typeof(Startup).Assembly);

                var hostConfig = sp.GetRequiredService<IConfiguration>();
                var options = new ConfigurationReaderOptions(functionDependencyContext) { SectionName = "AzureFunctionsJobHost:Serilog" };
                var logger = new LoggerConfiguration()
                    .ReadFrom.Configuration(hostConfig, options)
                    .CreateLogger();

                return new SerilogLoggerProvider(logger, dispose: true);
            });
        }
    }
}
